﻿using NetworkLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PBO.Network.FourPlayer
{
    public class FourPlayerServer : BattleServer, IFourPlayerServerService
    {
        private Dictionary<byte, string> _positions = new Dictionary<byte, string>();
        private object _locker = new object();

        public FourPlayerServer(string serverPlayer)
            : base((int)ServerPort.FourPlayerServerPort)
        {
            base.OnClientDisconnected += FourPlayerServer_OnClientDisconnected;

            _positions[1] = serverPlayer;
            for (byte i = 2; i < 5; i++)
            {
                _positions[i] = string.Empty;
            }
        }

        private void FourPlayerServer_OnClientDisconnected(ClientSession client)
        {
            lock (_locker)
            {
                var session = client as FourPlayerSession;
                if (session.Position != 0)
                {
                    SetPosition(session.Position, "");
                }
            }
        }

        protected override ClientSession CreateClientSession(int sessionID, IReactor reactor)
        {
            return new FourPlayerSession(sessionID, reactor, Buffered);
        }

        private void SetPosition(byte position, string player)
        {
            _positions[position] = player;
            var rsp = new PositionResponse() { position = position, player = player };
            base.BroadCast(EnumFourPlayerMethods.Client_SetPosition_Hash, rsp);
            if (OnPositionSet != null) OnPositionSet(position, player);
        }

        #region IFourPlayerServerService

        public event Action<byte, string> OnPositionSet;

        public void StartBattle()
        {
            base.BroadCast(EnumFourPlayerMethods.Client_StartBattle_Hash, "0");
        }

        #endregion

        #region event

        protected void OnLogon(int sessionID, int identity)
        {
            lock (_locker)
            {
                for (byte i = 1; i < 5; i++)
                {
                    var rsp = new PositionResponse() { position = i, player = _positions[i] };
                    SendData(sessionID, EnumFourPlayerMethods.Client_SetPosition_Hash, rsp);
                }
            }
        }

        protected void OnSetPosition(int sessionID, byte position, string player)
        {
            lock (_locker)
            {
                if (_positions[position] == "")
                {
                    var session = GetClient(sessionID) as FourPlayerSession;
                    if (session.Position != 0)
                    {
                        SetPosition(session.Position, "");
                    }
                    SetPosition(position, player);
                    session.Position = position;
                    base.SendData(sessionID, EnumFourPlayerMethods.Client_SetPositionSuccess_Hash, position);
                }
            }
        }

        protected void OnStartBattle(int sessionID)
        { }

        protected void OnClose(int sessionID)
        { }

        #endregion

        protected override void OnReceiveData(int sessionID, int method, string json)
        {
            base.OnReceiveData(sessionID, method, json);
            switch (method)
            {
                case EnumFourPlayerMethods.Server_Logon_Hash:
                    OnLogon(sessionID, int.Parse(json));
                    break;
                case EnumFourPlayerMethods.Server_SetPosition_Hash:
                    var rsp = StringUtils.ParseResponse<PositionResponse>(json);
                    OnSetPosition(sessionID, rsp.position, rsp.player);
                    break;
                case EnumFourPlayerMethods.Server_StartBattle_Hash:
                    OnStartBattle(sessionID);
                    break;
                case EnumFourPlayerMethods.Server_Close_Hash:
                    OnClose(sessionID);
                    break;
            }
        }
    }
}
